
#pragma once

#include "stdafx.h"


class Technique
{
public:
	Technique ( LPCSTR name, Effect const & rEffect, ID3D10Device & rDevice, D3D10_INPUT_ELEMENT_DESC * aLayoutElements, u32 uLayoutElementCount )
		: pTechnique(rEffect.pEffect->GetTechniqueByName(name))
		, pInputLayout(NULL)
	{
		HRESULT hResult = S_OK;
		D3D10_PASS_DESC PassDesc;
		pTechnique->GetPassByIndex(0)->GetDesc(&PassDesc);
		hResult = rDevice.CreateInputLayout( aLayoutElements, uLayoutElementCount, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &pInputLayout );
	}

	~Technique()
	{
		pTechnique = NULL;
		if( pInputLayout )
		{
			pInputLayout->Release();
			pInputLayout = NULL;
		}
	}

	void PreRender ( ID3D10Device & rDevice, VertexBuffer const & rBuffer )
	{
		// Update Buffers.
		rBuffer.UpdateBuffers();

		// Set Layout
		rDevice.IASetInputLayout( pInputLayout );

		// Set Vert Buffer.
		u32 uStride = rBuffer.GetVertStride();
		u32 uOffset = 0;
		ID3D10Buffer * pVertexBuffer = rBuffer.GetVertexBuffer();
		rDevice.IASetVertexBuffers( 0, 1, &pVertexBuffer, &uStride, &uOffset );

		// Set Index Buffer.
		rDevice.IASetIndexBuffer( rBuffer.GetIndexBuffer(), rBuffer.GetIndexFormat(), 0 );

		// Set the Primitive Topology.
		rDevice.IASetPrimitiveTopology( rBuffer.GetBufferTopology() );
	}

	void Render ( ID3D10Device & rDevice, VertexBuffer const & rBuffer )
	{
		D3D10_TECHNIQUE_DESC techDesc;
		pTechnique->GetDesc( &techDesc );

		for( UINT p = 0; p < techDesc.Passes; ++p )
		{
			pTechnique->GetPassByIndex(p)->Apply(0);

			u32 uIndexCount = rBuffer.GetIndexCount();
			rDevice.DrawIndexed( uIndexCount, 0, 0 );
		}
	}

	inline ID3D10EffectTechnique * GetTechnique ( ) const { return pTechnique; }

private:
	ID3D10EffectTechnique * pTechnique;
	ID3D10InputLayout * pInputLayout;
};


